//never include this file directly, please include "MathUtils.h"
#include <math.h>

namespace math
{

	inline bool IsOdd(const UInt i_number)
	{
		return i_number & 1;
	}

	inline bool IsPrime(const UInt i_number)
	{
		if (!IsOdd(i_number))
			return false;

		const UInt bound = static_cast<UInt>(sqrt(static_cast<Real>(i_number)));
		for (UInt i = 3; i <= bound; i+=2) //or: for (UInt i = 3; i*i <= i_number; i+=2)
			if (i_number % i == 0)
				return false;
		
		return true;
	}

	inline bool IsPalindrome(const UInt i_number) 
	{
		UInt32 pal = 0;
		UInt32 value = i_number;

		while (value > 0)
		{
			pal = pal * 10 + value % 10;
			value /= 10;
		}

		return (pal == i_number);
	}

	inline UInt GetMCD(const UInt i_first, const UInt i_second)
	{
		UInt num1(i_first);
		UInt num2(i_second);

		if (num1 < num2)
			std::swap(num1,num2);

		while (num2)
		{
			num1 = num1 % num2;
			std::swap(num1,num2);
		}
		return num1;
	}

	inline UInt GetMCM(const UInt i_first, const UInt i_second)
	{
		//don't know if it's better to evaulate MCM with respect MCD
		//or to write in place a solution
		const UInt ret = (i_first/GetMCD(i_first, i_second))*i_second;
		return ret;
	}
	
	template<typename Container>
	inline UInt GetMCM(const Container& i_container)
	{
		Container::const_iterator first = i_container.begin();
		Container::const_iterator last = i_container.end();

		if(first==last)
			return 0;

		UInt ret= *first;
		while(++first != last)
			ret = GetMCM(ret, *first);

		return ret;
	}

	template<typename Container>
	inline UInt GetMCD(const Container& i_container)
	{
		Container::const_iterator first = i_container.begin();
		Container::const_iterator last = i_container.end();

		if(first==last)
			return 0;

		UInt ret= *first;
		while(++first != last)
			ret = GetMCD(ret, *first);

		return ret;
	}

	inline UInt GetNumberOfDivisors(const UInt i_number)
	{
		UInt divisors = 0;

		UInt i = 1;
		for (; i*i < i_number; ++i)
		{
			if (i_number % i == 0)
				divisors+=2;
		}
		if(i*i==i_number)
			++divisors;

		return divisors;
	}

	inline void ComputePrimeFactors(const UInt64 i_number, FactorExpList& o_factorList)
    {
        UInt64 currNumber = i_number;
        UInt currFactor = 2;

        while(currNumber >= currFactor)
        {
            FactorExp push(currFactor, 0);
            while(!(currNumber % currFactor))
            {
                currNumber /= currFactor;
                ++(push.second);
            }

            if(push.second)
                o_factorList.push_back(push);
            ++currFactor;
        }
    }

	/*
	* @ugasoft: 
		I propose to use this function for integer exponentiation.
		Andrea.
	*/
	inline int IntPow(const int& base, const int& exponent)
	{
		int result = 1;
		for (int i = 0;i < exponent;++i)
			result *= base;
		return result;
	}
}

#include "MathUtilsRejected.inl"